package com.jboost.modules.system.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jboost.common.aspect.annotation.LimitSubmit;
import com.jboost.common.config.CommonConfig;
import com.jboost.common.constant.enums.ResultCode;
import com.jboost.common.domain.DomainConstant;
import com.jboost.common.util.encryption.AesEncryptUtil;
import com.jboost.config.init.WxMaConfiguration;
import com.jboost.config.mybatis.DomainContext;
import com.jboost.modules.system.entity.*;
import com.jboost.modules.system.service.*;
import com.jboost.modules.system.util.JsonUtils;
import com.jboost.modules.system.vo.WxMaJscode2SessionVo;
import com.jboost.modules.system.vo.WxMaPhoneInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.shiro.SecurityUtils;
import com.jboost.common.api.vo.Result;
import com.jboost.common.constant.CacheConstant;
import com.jboost.common.constant.CommonConstant;
import com.jboost.common.system.api.ISysBaseAPI;
import com.jboost.modules.base.service.BaseCommonService;
import com.jboost.common.system.util.JwtUtil;
import com.jboost.common.system.vo.LoginUser;
import com.jboost.common.util.*;
import com.jboost.common.util.encryption.EncryptedString;
import com.jboost.modules.system.model.SysLoginModel;
import com.jboost.modules.system.util.RandImageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/sys")
@Api(tags = "用户登录")
@Slf4j
public class LoginController {
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysAccountService sysAccountService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysLogService logService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ISysDictService sysDictService;
    @Autowired
    private ISysThirdAccountService sysThirdAccountService;
    @Resource
    private BaseCommonService baseCommonService;
    @Autowired
    private ISysLogService sysLogService;

    private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";

    @ApiOperation("密码登录接口")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result<JSONObject> login(@RequestBody @Validated SysLoginModel sysLoginModel, @RequestHeader(value = CommonConstant.DOMAIN) String domain) {
//		DomainContext.setDomain(domain);
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
//        String phone = sysLoginModel.getPhone();
        String password = sysLoginModel.getPassword();
        if (password.length() > 20){
            //解密一下
            try {
                password = AesEncryptUtil.desEncrypt(password);
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("解密后的密码是："+password);
        }
        //update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题
        //前端密码加密，后端进行密码解密
        //password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
        //update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题

        //update-begin-author:taoyan date:20190828 for:校验验证码
//        String captcha = sysLoginModel.getCaptcha();
//        if (captcha == null) {
//            result.error500("验证码无效");
//            return result;
//        }
//        String lowerCaseCaptcha = captcha.toLowerCase();
//        String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + sysLoginModel.getCheckKey(), "utf-8");
//        Object checkCode = redisUtil.get(realKey);
//        //当进入登录页时，有一定几率出现验证码错误 #1714
//        if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
//            result.error500("验证码错误");
//            return result;
//        }
        //update-end-author:taoyan date:20190828 for:校验验证码

        //1. 校验用户是否有效
        //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        if (StringUtils.isEmpty(username)) {
            result.error500("请输入手机号");
            return result;
        }
        //先查产品域下是不是有对应的用户和账号
        SysUser sysUser = sysUserService.getDomainUserByName(username,domain);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        JSONObject business = null;
//        if(sysUser.getDomain().equals(DomainConstant.BUSINESS.getCode())){
//            //机构账号登录需要校验机构状态
//            if ("invalid".equals(business.getString("status")) ){
//                result.error500("账号已关闭，请联系管理员开通");
//                return result;
//            }
//        }
//		SysAccount sysAccount = sysAccountService.getAccountByNameAndDomain(username,phone);
//		//检查账号
//		result = sysAccountService.checkAccountIsEffective(sysAccount);
//		if(!result.isSuccess()) {
//			return result;
//		}

        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(sysUser.getUsername(), password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("账号名或密码错误");
            return result;
        }

        //用户登录信息
//		List<SysUser> sysUserList = sysUserService.getUserByAccountId(sysAccount.getId());
//
//		if(null == sysUserList || sysUserList.size() == 0){
//			result.error500("找不到对应的用户");
//			return result;
//		}
        //状态正常的用户id
//		List<String> userIds = sysUserList.stream().filter( u->1==u.getStatus() ).map(u->u.getId()).collect(Collectors.toList());
//		if(CollUtil.isEmpty(userIds)){
//			result.errorCode(ResultCode.FORBIDDEN.getCode(),"您的账户已停用，请联系材神云业务人员进行处理！");
//			return result;
//		}
        //取最后一次登录的状态正常的角色用户
        //pc最后登录时间
//		SysLog pcSysLog = sysLogService.getOne(new QueryWrapper<SysLog>().lambda().eq(SysLog::getLogType,CommonConstant.LOG_TYPE_1).eq(SysLog::getOperateType,CommonConstant.LOG_OPERATE_TYPE_PC).in(SysLog::getUserid, userIds ).orderByDesc(SysLog::getCreateTime).last(" limit 1") );
//		SysUser sysUser = null;
//		if (null!=pcSysLog)
//			sysUser = sysUserList.stream().filter(u->u.getId().equals(pcSysLog.getUserid())).findFirst().orElse(null);
//		if(null==sysUser)
//			sysUser = sysUserList.get(0);
        //检查用户
//        result = sysUserService.checkUserIsEffective(sysUser);
//        if (!result.isSuccess()) {
//            return result;
//        }
//		sysUser.setUsername(sysAccount.getAccountName());
        userInfo(sysUser, result);
//        List<DictModel> modelList = sysDictService.queryDictItemsByCode(CommonConstant.DOMAIN_DICT_CODE);
//        DictModel dictModel = null;

        //update-begin--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        baseCommonService.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, CommonConstant.LOG_OPERATE_TYPE_PC, loginUser);
        //update-end--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        if(DomainConstant.BUSINESS.getCode().equals(domain)){
            // 机构登录返回机构信息
            result.getResult().put("business",business);
        }
        return result;
    }

    @ApiOperation("使用 token 登录接口")
    @RequestMapping(value = "/loginByToken", method = RequestMethod.POST)
    public Result<JSONObject> loginByToken(@RequestBody JSONObject jsonObject, @RequestHeader(value = CommonConstant.X_ACCESS_TOKEN) String token) {
        String userId = jsonObject.getString("userId");
        String userName = jsonObject.getString("userName");
        String domain = jsonObject.getString("domain");
        Result<JSONObject> result = new Result<JSONObject>();
        //确认 token
        if (oConvertUtils.isEmpty(token)) {
            return result.error500("token 不能为空！");
        }
        String tokenUserName = JwtUtil.getUsername(token);
        if (StringUtils.isEmpty(tokenUserName)) {
            return result.error500("token 无效！");
        }
//		LoginUser tokenUser = sysBaseAPI.getUserByName(tokenUserName);
        //切换到目标产品域查询用户
        DomainContext.setDomain(domain);
        LoginUser loginUser = sysBaseAPI.getUserById(userId);
        if (null == loginUser) {
            return result.error500("切换的用户不存在！");
        }
//		SysAccount loginAccount = sysAccountService.getAccountByNameAndDomain(loginUser.getUsername(),null);
//		if(null == loginAccount){
//			return result.error500("切换的账号不存在！");
//		}
        String username = loginUser.getUsername();
        //清除旧登录信息
        baseCommonService.addLog("loginByToken-用户名: " + loginUser.getRealname() + ",退出成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        //清空用户登录Token缓存
        redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
        //清空用户登录Shiro权限缓存
        redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + loginUser.getId());
        //清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
        redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, loginUser.getUsername()));
        //调用shiro的logout
        SecurityUtils.getSubject().logout();

        //用户新登录信息
        SysUser sysUser = sysUserService.getById(userId);
        userInfo(sysUser, result);
        BeanUtils.copyProperties(sysUser, loginUser);
        //update-begin--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        baseCommonService.addLog("loginByToken-用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        //update-end--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        return result;
    }

    @ApiOperation("使用 token 获取用户信息")
    @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
    public Result<JSONObject> getUserInfo(@RequestHeader(value = CommonConstant.X_ACCESS_TOKEN) String token) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = JwtUtil.getUsername(token);
        String userId = JwtUtil.getUserId(token);
        //1. 校验用户是否有效
        SysUser sysUser = sysUserService.getById(userId);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        if( !StringUtils.isEmpty(sysUser.getAvatar()) ){
            sysUser.setAvatarFile( sysBaseAPI.getFileById(sysUser.getAvatar()) );
        }
        userInfo(sysUser, result);
        result.setMessage("成功");
        return result;
    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/logout")
    public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {
        //用户退出逻辑
        String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
        if (oConvertUtils.isEmpty(token)) {
            return Result.ok("已退出登录！");
        }
        String username = JwtUtil.getUsername(token);
        String userId = JwtUtil.getUserId(token);

        LoginUser sysUser = sysBaseAPI.getUserById(userId);
        if (sysUser != null) {
            //update-begin--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
            baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",退出成功！", CommonConstant.LOG_TYPE_1, null, sysUser);
            //update-end--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
            log.info(" 用户名:  " + sysUser.getRealname() + ",退出成功！ ");
            //清空用户登录Token缓存
            redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
            //清空用户登录Shiro权限缓存
            redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
            //清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
            //调用shiro的logout
            SecurityUtils.getSubject().logout();
            return Result.ok("退出登录成功！");
        } else {
            return Result.error("Token无效!");
        }
    }

    /**
     * 获取访问量
     *
     * @return
     */
    @GetMapping("loginfo")
    public Result<JSONObject> loginfo() {
        Result<JSONObject> result = new Result<JSONObject>();
        JSONObject obj = new JSONObject();
        //update-begin--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
        // 获取一天的开始和结束时间
        Calendar calendar = new GregorianCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date dayStart = calendar.getTime();
        calendar.add(Calendar.DATE, 1);
        Date dayEnd = calendar.getTime();
        // 获取系统访问记录
        Long totalVisitCount = logService.findTotalVisitCount();
        obj.put("totalVisitCount", totalVisitCount);
        Long todayVisitCount = logService.findTodayVisitCount(dayStart, dayEnd);
        obj.put("todayVisitCount", todayVisitCount);
        Long todayIp = logService.findTodayIp(dayStart, dayEnd);
        //update-end--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
        obj.put("todayIp", todayIp);
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * 获取访问量
     *
     * @return
     */
    @GetMapping("visitInfo")
    public Result<List<Map<String, Object>>> visitInfo() {
        Result<List<Map<String, Object>>> result = new Result<List<Map<String, Object>>>();
        Calendar calendar = new GregorianCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date dayEnd = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date dayStart = calendar.getTime();
        List<Map<String, Object>> list = logService.findVisitCount(dayStart, dayEnd);
        result.setResult(oConvertUtils.toLowerCasePageList(list));
        return result;
    }

    /**
     * 测试获取用户
     *
     * @return
     */
    @GetMapping("userInfo")
    public Result<?> userInfo(@RequestParam(name = "name") String name) {
        Result<SysUser> result = new Result<SysUser>();
        result.setResult(sysUserService.getUserByName(name));
        return result;
    }


    /**
     * 登陆成功选择用户当前部门
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
    public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = user.getUsername();
        if (oConvertUtils.isEmpty(username)) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            username = sysUser.getUsername();
        }
        String orgCode = user.getOrgCode();
        this.sysUserService.updateUserDepart(username, orgCode);
        SysUser sysUser = sysUserService.getUserByName(username);
        JSONObject obj = new JSONObject();
        obj.put("userInfo", sysUser);
        result.setResult(obj);
        return result;
    }

    /**
     * 短信登录接口
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("发送短信")
    @PostMapping(value = "/sms")
    public Result<String> sms(@RequestBody @ApiParam(value = "mobile，smsmode： 0-登录验证码、1-注册验证码、2-微信绑定、忘记密码验证码") JSONObject jsonObject, @RequestHeader(value = CommonConstant.DOMAIN, required = false) String domain) {
//		DomainContext.setDomain(domain);
        Result<String> result = new Result<String>();
        String mobile = jsonObject.get("mobile").toString();

        Pattern p = Pattern.compile(CommonConstant.PHONE_REGEXP);
        Matcher m = p.matcher(mobile);
        if(!m.matches()){
            result.setMessage("不是正确的手机号！");
            result.setSuccess(false);
            return result;
        }
        //手机号模式 登录模式: "2"  注册模式: "1"
        String smsmode = jsonObject.get("smsmode").toString();
        log.info(mobile);
        if (oConvertUtils.isEmpty(mobile)) {
            result.setMessage("手机号不允许为空！");
            result.setSuccess(false);
            return result;
        }
        Object object = redisUtil.get(mobile);
        if (object != null) {
            result.setMessage("验证码10分钟内，仍然有效！");
            result.setSuccess(false);
            return result;
        }

        JSONObject obj = new JSONObject();
        //随机数
        String captcha = RandomUtil.randomNumbers(6);
        if ( "local".equals(CommonConfig.env) || "dev".equals(CommonConfig.env) || "test".equals(CommonConfig.env)){
            //先固定123456
            captcha = "123456";
        }
        obj.put("code", captcha);
        try {
            boolean b = false;
            //注册模板
            if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
                SysUser sysUser = sysUserService.getUserByPhone(mobile);
                if (sysUser != null) {
                    result.error500(" 手机号已经注册，请直接登录！");
                    baseCommonService.addLog("手机号已经注册，请直接登录！", CommonConstant.LOG_TYPE_1, null);
                    return result;
                }
                b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.GET_CODE);
            } else {
                //登录模式，校验用户有效性
                SysUser sysUser = sysUserService.getDomainUserByName(mobile,domain);
                result = sysUserService.checkUserIsEffective(sysUser);
                if (!result.isSuccess()) {
                    String message = result.getMessage();
                    if ("该用户不存在，请注册".equals(message)) {
                        result.error500("该用户不存在或未绑定手机号");
                    }
                    return result;
                }

                /**
                 * smsmode 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
                 */
                if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
                    //登录模板
//                    result.error500("该短信模板未配置，请联系管理员！");
//                    return result;
					b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.GET_CODE);
                } else if (CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
                    //微信绑定、忘记密码验证码 单纯下发一个验证码
                    b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.GET_CODE);
                }
            }

            if (b == false) {
                result.setMessage("短信验证码发送失败,请稍后重试");
                result.setSuccess(false);
                return result;
            }
            log.info("短信验证码：" + mobile + ":" + captcha);
            //验证码10分钟内有效
            redisUtil.set(mobile, captcha, 600);
            //update-begin--Author:scott  Date:20190812 for：issues#391
            //result.setResult(captcha);
            //update-end--Author:scott  Date:20190812 for：issues#391
            result.setSuccess(true);

        } catch (ClientException e) {
            e.printStackTrace();
            result.error500(" 短信接口未配置，请联系管理员！");
            return result;
        }
        return result;
    }


    /**
     * 手机号登录接口
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("手机短信登录接口")
    @PostMapping("/phoneLogin")
    public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
        Result<JSONObject> result = new Result<JSONObject>();
        String phone = jsonObject.getString("mobile");

        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }

        String smscode = jsonObject.getString("captcha");
        Object code = redisUtil.get(phone);
        if (!smscode.equals(code)) {
            result.setMessage("验证码错误，请重新输入");
            return result;
        }
        //用户信息
        userInfo(sysUser, result);
        //添加日志
        baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null);

        return result;
    }


    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
//		SysAccount account = sysAccountService.getAccountByNameAndDomain(sysUser.getUsername(),null);
//		if (null == account){
//			return result;
//		}
        return sysUserService.userInfo(sysUser,result);
    }

    /**
     * 获取加密字符串
     *
     * @return
     */
    @GetMapping(value = "/getEncryptedString")
    public Result<Map<String, String>> getEncryptedString() {
        Result<Map<String, String>> result = new Result<Map<String, String>>();
        Map<String, String> map = new HashMap<String, String>();
        map.put("key", EncryptedString.key);
        map.put("iv", EncryptedString.iv);
        result.setResult(map);
        return result;
    }

    /**
     * 后台生成图形验证码 ：有效
     *
     * @param response
     * @param key
     */
    @ApiOperation("获取验证码")
    @GetMapping(value = "/randomImage/{key}")
    public Result<String> randomImage(HttpServletResponse response, @PathVariable String key) {
        Result<String> res = new Result<String>();
        try {
            String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
            String lowerCaseCode = code.toLowerCase();
            String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8");
            redisUtil.set(realKey, lowerCaseCode, 60);
            log.info("###########" + code + "#############");
            String base64 = RandImageUtil.generate(code);
            res.setSuccess(true);
            res.setResult(base64);
        } catch (Exception e) {
            res.error500("获取验证码出错" + e.getMessage());
            e.printStackTrace();
        }
        return res;
    }

    /**
     * app登录
     *
     * @param sysLoginModel
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/mLogin", method = RequestMethod.POST)
    public Result<JSONObject> mLogin(@RequestBody @Validated SysLoginModel sysLoginModel) throws Exception {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = sysLoginModel.getUsername();
        String password = sysLoginModel.getPassword();

        //1. 校验用户是否有效
        SysUser sysUser = sysUserService.getUserByName(username);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
//		SysAccount sysAccount = sysAccountService.getAccountByNameAndDomain(username,null);
//		result = sysAccountService.checkAccountIsEffective(sysAccount);
//		if(!result.isSuccess()) {
//			return result;
//		}

        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }
//		List<SysUser> sysUserList = sysUserService.getUserByAccountId(sysAccount.getId());
//		todo 需要选出其中一个角色的用户
//		SysUser sysUser = sysUserList.get(0);
        String orgCode = sysUser.getOrgCode();
        if (oConvertUtils.isEmpty(orgCode)) {
            //如果当前用户无选择部门 查看部门关联信息
            List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
            if (departs == null || departs.size() == 0) {
                result.error500("用户暂未归属部门,不可登录!");
                return result;
            }
            orgCode = departs.get(0).getOrgCode();
            sysUser.setOrgCode(orgCode);
            this.sysUserService.updateUserDepart(username, orgCode);
        }
        JSONObject obj = new JSONObject();
        //用户登录信息
        obj.put("userInfo", sysUser);

        // 生成token
        String token = JwtUtil.sign(sysUser.getId(), username, syspassword);
        // 设置超时时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);

        //token 信息
        obj.put("token", token);
        result.setResult(obj);
        result.setSuccess(true);
        result.setCode(200);
        baseCommonService.addLog("用户名: " + username + ",登录成功[app端]！", CommonConstant.LOG_TYPE_1, CommonConstant.LOG_OPERATE_TYPE_APP);
        return result;
    }

    /**
     * 图形验证码
     *
     * @param sysLoginModel
     * @return
     */
    @RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
    public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel) {
        String captcha = sysLoginModel.getCaptcha();
        String checkKey = sysLoginModel.getCheckKey();
        if (captcha == null) {
            return Result.error("验证码无效");
        }
        String lowerCaseCaptcha = captcha.toLowerCase();
        String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + checkKey, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {
            return Result.error("验证码错误");
        }
        return Result.ok();
    }

    /**
     * loginByWechat
     *
     * @param code
     * @return
     */
    @ApiOperation("微信小程序登录接口")
    @GetMapping("/loginByWechat")
    public Result<WxMaJscode2SessionVo> loginByWechat(@RequestParam(name = "appId", required = false) String appId, @RequestParam(name = "code") String code, @RequestHeader(value = CommonConstant.DOMAIN, required = false) String domain) {
        WxMaJscode2SessionVo vo = new WxMaJscode2SessionVo();
        if (StringUtils.isEmpty(code)) {
            return Result.ERROR("empty jscode", vo);
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appId);
//		if(StringUtils.isEmpty(domain))
//		    domain = DomainConstant.PARTNER.getCode();
//        DomainContext.setDomain(domain);
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);

            BeanUtils.copyProperties(session, vo);
            //先使用 openId
            SysThirdAccount thirdAccount = sysThirdAccountService.getOne(new QueryWrapper<SysThirdAccount>().lambda().eq(SysThirdAccount::getThirdType, SysThirdAccount.THIRD_TYPE_WECHAT).eq(SysThirdAccount::getThirdUserUuid, session.getOpenid()).orderByDesc(SysThirdAccount::getId).last(" limit 1"));
            //openId 保存到 redis
            redisUtil.set(CommonConstant.PREFIX_WECHAT_OPEN_ID + session.getOpenid(), 0, JwtUtil.EXPIRE_TIME / 1000);
            SysUser sysUser = null;
            SysAccount account = null;
            if (null != thirdAccount && !StringUtils.isEmpty(thirdAccount.getSysUserId())) {
                sysUser = sysUserService.getById(thirdAccount.getSysUserId());
                //sysUser.setLoginType(2);
//				account = sysAccountService.getAccountByUserId(thirdAccount.getSysUserId());

                Result result = sysUserService.checkUserIsEffective(sysUser);
                if (!result.isSuccess())
                    return result;
                sysUser.setPassword(sysUser.getPassword());
                sysUser.setSalt(sysUser.getSalt());
                Result<JSONObject> resultJson = new Result<JSONObject>();
                userInfo(sysUser, resultJson);
                vo.setCscUserInfo(resultJson.getResult());
                LoginUser user = new LoginUser();
                user.setId(sysUser.getId());
                user.setRealname(sysUser.getUsername());
                user.setUsername(sysUser.getUsername());
                baseCommonService.addLog("用户: " + sysUser.getId() + "openId:" + session.getOpenid() + ",登录成功[小程序端]！", CommonConstant.LOG_TYPE_1, CommonConstant.LOG_OPERATE_TYPE_WX, user);

            }
            return Result.OK(vo);
        } catch (WxErrorException e) {
            return Result.ERROR(e.toString(), vo);
        }
    }

    /**
     * <pre>
     * 获取微信用户绑定手机号信息
     * </pre>
     */
    @ApiOperation("解密/获取微信用户绑定手机号信息，并返回手机号有没有对应的 csc 用户")
    @GetMapping("/getWechatPhone")
    public String phone(@RequestParam(name = "appId", required = false) String appid, @RequestParam String sessionKey, @RequestParam String encryptedData, @RequestParam String iv) {
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);

        // 用户信息校验
//		if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
//			return "user check failed";
//		}

        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        WxMaPhoneInfoVo infoVo = new WxMaPhoneInfoVo();
        BeanUtils.copyProperties(phoneNoInfo, infoVo);
        //检查手机号有没有材神云账号
        SysUser user = sysUserService.getUserByPhone(phoneNoInfo.getPurePhoneNumber());
//		sysUserService.checkUserIsEffective(user);
        if (null != user)
            infoVo.setPhoneUser(user);
        return JsonUtils.toJson(phoneNoInfo);
    }

    /**
     * <pre>
     * 检查手机号是不是有用户
     * </pre>
     */
    @ApiOperation("检查手机号是不是有用户：返回 code 会有两个值：500 、 1 ；只有 code==1 才是有对应的账号的")
    @GetMapping("/checkUserByPhone")
    public Result checkUserByPhone(@RequestParam(name = "appId", required = false) String appid, @RequestParam(name = "openId") String openId, @RequestParam(name = "phone", required = true) String phone, @RequestHeader(value = CommonConstant.DOMAIN, required = false) String domain) {
        // 需要限制调用
        Object queryCount = redisUtil.get(CommonConstant.PREFIX_WECHAT_OPEN_ID + openId);
        if (queryCount == null) {
            //openId非法
            return Result.error(ResultCode.PARAMETER_VERIFY_FAIL);
        }
        if (queryCount instanceof Integer) {
            Integer count = (Integer) queryCount;
            if (count > 4) {
                //openId 30分钟不能超过5次；
                return Result.error(ResultCode.OPERATION_TOO_FREQUENTLY);
            }
        }
        redisUtil.incr(CommonConstant.PREFIX_WECHAT_OPEN_ID + openId, 1);

        //检查手机号有没有账号
//		DomainContext.setDomain(domain);
        SysUser user = sysUserService.getUserByPhone(phone);
        //手机是不是有绑定了其他微信
        if (null != user) {
            SysThirdAccount old = sysThirdAccountService.getOne(new QueryWrapper<SysThirdAccount>().lambda().eq(SysThirdAccount::getSysUserId, user.getId()));
            if (null != old) {
                return Result.error(ResultCode.USER_BOUND_WECHAT);
            }
        }
        return sysUserService.checkUserIsEffectiveNew(user);
    }

    /**
     * 绑定微信小程序
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("绑定微信小程序")
    @PostMapping("/wechatBinding")
    // 防止连续多次调用
    @LimitSubmit(key = "csc:limitSubmit:sys:wechatBinding:#jsonObject")
    public Result<JSONObject> wechatBinding(@RequestBody @ApiParam(value = "mobile,openId,captcha") JSONObject jsonObject, @RequestHeader(value = CommonConstant.DOMAIN, required = false) String domain) {
        Result<JSONObject> result = new Result<JSONObject>();
        String phone = jsonObject.getString("mobile");
        String uuid = jsonObject.getString("openId");
        String smscode = jsonObject.getString("captcha");
        Object code = redisUtil.get(phone);
        if (!smscode.equals(code)) {
            result.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
            result.setMessage("验证码错误，请重新输入");
            return result;
        }
//		if(!DomainConstant.PARTNER.getCode().equals(domain)){
//			result.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
//			result.setMessage("产品域不匹配");
//			return result;
//		}
//		DomainContext.setDomain(domain);
        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }

        //新增第三方登录
        //确认一下微信是不有绑定过其他账号
        SysThirdAccount old = sysThirdAccountService.getOne(new QueryWrapper<SysThirdAccount>().lambda().eq(SysThirdAccount::getThirdUserUuid, uuid));
        if (null != old) {
            result.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
            result.setMessage("该微信已绑定了其他材神云账号");
            return result;
        }
        SysThirdAccount thirdAccount = new SysThirdAccount();
        thirdAccount.setSysUserId(sysUser.getId());
        thirdAccount.setThirdUserUuid(uuid);
        thirdAccount.setThirdType(SysThirdAccount.THIRD_TYPE_WECHAT);
        sysThirdAccountService.save(thirdAccount);
        //登录
        userInfo(sysUser, result);

        result.setSuccess(true);
        result.setMessage("绑定成功，登录成功");

        LoginUser user = new LoginUser();
        user.setId(sysUser.getId());
        user.setRealname(sysUser.getUsername());
        user.setUsername(sysUser.getUsername());

        baseCommonService.addLog("用户: " + sysUser.getId() + "openId:" + uuid + ",登录成功[小程序端]！", CommonConstant.LOG_TYPE_1, CommonConstant.LOG_OPERATE_TYPE_WX, user);
        return result;
    }
}
